xen memory allocator: Allow per-domain bitwidth restrictions.
authorKeir Fraser <keir@xensource.com>
Sat, 24 Feb 2007 13:57:34 +0000 (13:57 +0000)
committerKeir Fraser <keir@xensource.com>
Sat, 24 Feb 2007 13:57:34 +0000 (13:57 +0000)
Original patch by Jan Beulich <jbeulich@novell.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
xen/arch/x86/domain.c
xen/arch/x86/domain_build.c
xen/arch/x86/x86_64/mm.c
xen/common/page_alloc.c
xen/include/asm-ia64/mm.h
xen/include/asm-powerpc/mm.h
xen/include/asm-x86/domain.h
xen/include/asm-x86/mm.h

index bca683c59bf5db0f01c19cffbb9c0819feb7678c..65164c10b30e632b4778aa2e9497749e7deb5226 100644 (file)
@@ -255,7 +255,7 @@ static void release_compat_l4(struct vcpu *v)
 
 static inline int may_switch_mode(struct domain *d)
 {
-    return 1; /* XXX */
+    return (d->tot_pages == 0);
 }
 
 int switch_native(struct domain *d)
@@ -263,7 +263,7 @@ int switch_native(struct domain *d)
     l1_pgentry_t gdt_l1e;
     unsigned int vcpuid;
 
-    if ( !d )
+    if ( d == NULL )
         return -EINVAL;
     if ( !may_switch_mode(d) )
         return -EACCES;
@@ -283,6 +283,8 @@ int switch_native(struct domain *d)
             release_compat_l4(d->vcpu[vcpuid]);
     }
 
+    d->arch.physaddr_bitsize = 64;
+
     return 0;
 }
 
@@ -291,7 +293,7 @@ int switch_compat(struct domain *d)
     l1_pgentry_t gdt_l1e;
     unsigned int vcpuid;
 
-    if ( !d )
+    if ( d == NULL )
         return -EINVAL;
     if ( compat_disabled )
         return -ENOSYS;
@@ -313,6 +315,10 @@ int switch_compat(struct domain *d)
             return -ENOMEM;
     }
 
+    d->arch.physaddr_bitsize =
+        fls((1UL << 32) - HYPERVISOR_COMPAT_VIRT_START(d)) - 1
+        + (PAGE_SIZE - 2);
+
     return 0;
 }
 
index b3e19172d70e284c135415369084f1f4cf49e098..841f181f9933f427d68a371e79b6b5a113eea7e7 100644 (file)
@@ -357,7 +357,11 @@ int construct_dom0(struct domain *d,
 
         value = (parms.virt_hv_start_low + mask) & ~mask;
 #ifdef CONFIG_COMPAT
-        HYPERVISOR_COMPAT_VIRT_START(d) = max_t(unsigned int, m2p_compat_vstart, value);
+        HYPERVISOR_COMPAT_VIRT_START(d) =
+            max_t(unsigned int, m2p_compat_vstart, value);
+        d->arch.physaddr_bitsize = !IS_COMPAT(d) ? 64 :
+            fls((1UL << 32) - HYPERVISOR_COMPAT_VIRT_START(d)) - 1
+            + (PAGE_SIZE - 2);
         if ( value > (!IS_COMPAT(d) ?
                       HYPERVISOR_VIRT_START :
                       __HYPERVISOR_COMPAT_VIRT_START) )
index b098b21f5e682b39ce1c656154f2ae4c0461053f..8ff4da2769305770b3685a3478b9cc0c1b7b64a9 100644 (file)
@@ -409,6 +409,13 @@ int check_descriptor(const struct domain *dom, struct desc_struct *d)
     return 0;
 }
 
+unsigned int domain_clamp_alloc_bitsize(struct domain *d, unsigned int bits)
+{
+    if ( d == NULL )
+        return bits;
+    return min(d->arch.physaddr_bitsize, bits);
+}
+
 #include "compat/mm.c"
 
 /*
index c0a6f81858e8e67ebffce1055696206ad8451a89..b1d7647e476c1c7211c1c7b9d3e3263594672e25 100644 (file)
@@ -764,19 +764,21 @@ struct page_info *__alloc_domheap_pages(
     struct page_info *pg = NULL;
     cpumask_t mask;
     unsigned long i;
-    unsigned int bits = memflags >> _MEMF_bits, zone_hi;
+    unsigned int bits = memflags >> _MEMF_bits, zone_hi = NR_ZONES - 1;
 
     ASSERT(!in_irq());
 
-    if ( bits && bits <= PAGE_SHIFT + 1 )
-        return NULL;
-
-    zone_hi = bits - PAGE_SHIFT - 1;
-    if ( zone_hi >= NR_ZONES )
-        zone_hi = NR_ZONES - 1;
+    if ( bits )
+    {
+        bits = domain_clamp_alloc_bitsize(d, bits);
+        if ( bits <= (PAGE_SHIFT + 1) )
+            return NULL;
+        bits -= PAGE_SHIFT + 1;
+        if ( bits < zone_hi )
+            zone_hi = bits;
+    }
 
-    if ( NR_ZONES + PAGE_SHIFT > dma_bitsize &&
-         (!bits || bits > dma_bitsize) )
+    if ( (zone_hi + PAGE_SHIFT) >= dma_bitsize )
     {
         pg = alloc_heap_pages(dma_bitsize - PAGE_SHIFT, zone_hi, cpu, order);
 
index a232bd599c3b6d470bfcafefabbb333ad16f7783..fa0830d41435f1faeb57f83a69280a7d07432211 100644 (file)
@@ -509,4 +509,6 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg);
 int steal_page(
     struct domain *d, struct page_info *page, unsigned int memflags);
 
+#define domain_clamp_alloc_bitsize(d, b) (b)
+
 #endif /* __ASM_IA64_MM_H__ */
index e41580866b558ab15b06c6e51b491afcc08216ab..dd35d8887a8c3c0006fa0cd49d66391422651e62 100644 (file)
@@ -289,4 +289,7 @@ extern int steal_page(struct domain *d, struct page_info *page,
 /* XXX these just exist until we can stop #including x86 code */
 #define access_ok(addr,size) 1
 #define array_access_ok(addr,count,size) 1
+
+#define domain_clamp_alloc_bitsize(d, b) (b)
+
 #endif
index 3237f53e8e311451c0ac762085ffcccb91ae4ebf..c7618fbf3ab3478ede8e45e59739f29ecf7571ec 100644 (file)
@@ -179,6 +179,9 @@ struct arch_domain
     /* Pseudophysical e820 map (XENMEM_memory_map).  */
     struct e820entry e820[3];
     unsigned int nr_e820;
+
+    /* Maximum physical-address bitwidth supported by this guest. */
+    unsigned int physaddr_bitsize;
 } __cacheline_aligned;
 
 #ifdef CONFIG_X86_PAE
index 334d581479ba2bbb2df124753db97f3d317f565a..b240e4b5ca1acfec39d84e40133d9b8fbb543f32 100644 (file)
@@ -398,8 +398,11 @@ int map_ldt_shadow_page(unsigned int);
 
 #ifdef CONFIG_COMPAT
 int setup_arg_xlat_area(struct vcpu *, l4_pgentry_t *);
+unsigned int domain_clamp_alloc_bitsize(struct domain *d, unsigned int bits);
 #else
 # define setup_arg_xlat_area(vcpu, l4tab) 0
+# define domain_clamp_alloc_bitsize(d, b) (b)
 #endif
 
+
 #endif /* __ASM_X86_MM_H__ */